 /**
 * 逻辑、功能相关描述: <br>
 *
 * @author 付湘辉  <br>
 * 编写日期：2008-8-8  <br>
 */
package com.ce.pms.common.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.ce.pms.charge.model.SectSta;
import com.ce.pms.charge.vo.TransactionVO;
import com.ce.pms.common.vo.ChooseHouseVO;
import com.ce.pms.common.vo.ComLog4ceBizLogInfoVO;
import com.ce.pms.customer.vo.CustomerHouseVO;
import com.ce.pms.house.model.HouseGrp;
import com.ce.pms.house.vo.BuildingVO;
import com.ce.pms.occupation.vo.ThingHandoverItemVO;
import com.ce.pms.system.occupation.vo.ContractorInfoConfigVO;
import com.ce.pms.system.occupation.vo.PerfectItemTypeConfigVO;
import com.ce.pms.system.occupation.vo.SendDocumentItemConfigVO;
import com.ce.util.BlankUtil;

/**
 * 	名称: com.ce.pms.common.util.PmsUtilityComparator <br>
 *  一个PMS通用比较器
 *
 * @author  付湘辉  <br>
 * Created on： 2008-8-8 <br>
 * @author <br>
 * update on： <br>
 * why: <br>
 */
public class PmsUtilityComparator implements Comparator<Object> {

    /**
	 * 功能描述: 得到一个PMS比较器实例PmsUtilityComparator <br>
	 * <p><b>目前支持的对象类型列表：</p>
	 * <ol>
	 * <li><code>java.lang.String</code></li>
	 * <li><code>com.ce.pms.house.model.HouseGrp</code></li>
	 * <li><code>com.ce.pms.common.vo.ChooseHouseVO</code></li>
	 * <li><code>com.ce.pms.common.vo.TransactionVO</code></li>
	 * <li><code>com.ce.pms.common.vo.BuildingVO</code></li>
	 * </ol>
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public static PmsUtilityComparator getComparator(){
		return new PmsUtilityComparator();
	}
//	//
//	public static void main(String[] args) {
//		List<ChooseHouseVO> list = new ArrayList<ChooseHouseVO>();
//		ChooseHouseVO chv1 = new ChooseHouseVO(1, "1 1", "1栋－1单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(1, "1 2", "1栋－2单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(1, "1 3", "1栋－3单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(1, "1 4", "1栋－4单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(2, "2 23", "2栋－3单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(2, "1 23", "2栋－3单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(12, "12 3", "12栋－3单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(3, "3 3", "3栋－3单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(8, "12 4", "a栋－b单元");
//        list.add(chv1);
//
//        chv1 = new ChooseHouseVO(25, "25 23", "25栋－23单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(12, "12 5", "12栋－5单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(3, "3 13", "ad栋－d单元");
//        list.add(chv1);
//        chv1 = new ChooseHouseVO(25, "12 4", "25栋－14单元");
//        list.add(chv1);
//        System.out.println("排序前===================================");
//        for (ChooseHouseVO houseVO : list) {
//            System.out.println("------->:" +houseVO.getBuildSeqNo()+"   "+ houseVO.getSelectText());
//        }
//        System.out.println("重新打乱===================================");
//        Collections.shuffle(list);
//        for (ChooseHouseVO houseVO : list) {
//            System.out.println("------->:" +houseVO.getBuildSeqNo()+"   "+ houseVO.getSelectText());
//        }
//
//        Collections.sort(list, PmsUtilityComparator.getComparator());
//        System.out.println("排序后===================================");
//        for (ChooseHouseVO houseVO : list) {
//            System.out.println("------->:" +houseVO.getBuildSeqNo()+"   "+ houseVO.getSelectText());
//        }
//
//	}

	protected final Logger logger = Logger.getLogger(getClass());

	private PmsUtilityComparator(){

	}

	/**
	 * </p>功能描述: 一个PMS通用比较器方法。对不同的对象执行不同比较逻辑</p>
	 * <p><b>目前支持的对象类型列表：</p>
	 * <ol>
	 * <li><code>java.lang.String</code></li>
	 * <li><code>com.ce.pms.house.model.HouseGrp</code></li>
	 * <li><code>com.ce.pms.common.vo.ChooseHouseVO</code></li>
	 * <li><code>com.ce.pms.common.vo.TransactionVO</code></li>
	 * <li><code>com.ce.pms.common.vo.BuildingVO</code></li>
	 * <li><code>com.ce.pms.charge.model.SectSta</code></li>
	 * <li><code>com.ce.pms.customer.vo.CustomerHouseVO</code></li>
	 * <li><code>com.ce.pms.occupation.vo.ThingHandoverItemVO</code></li>
	 * <li><code>com.ce.pms.system.occupation.vo.SendDocumentItemConfigVO</code></li>
	 * <li><code>com.ce.pms.system.occupation.vo.PerfectItemTypeConfigVO</code></li>
	 * <li><code>com.ce.pms.system.occupation.vo.ContractorInfoConfigVO</code></li>
	 * <li><code>com.ce.pms.common.vo.ComLog4ceBizLogInfoVO</code></li>
	 * 
	 * </ol>
	 *
	 * @param o1
	 * @param o2
	 *
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 * @return 负整数、零或正整数。
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public int compare(Object o1, Object o2) {
		if (o1 instanceof String && o2 instanceof String) {
			return this.compareString((String)o1, (String)o2);
		}else if (o1 instanceof HouseGrp && o2 instanceof HouseGrp) {
			return this.compareHouseGrp((HouseGrp)o1, (HouseGrp)o2);
		}else if (o1 instanceof ChooseHouseVO && o2 instanceof ChooseHouseVO) {
			return this.compareChooseHouseVO((ChooseHouseVO)o1, (ChooseHouseVO)o2);
		}else if (o1 instanceof TransactionVO && o2 instanceof TransactionVO) {
			return this.compareTransactionVO((TransactionVO)o1, (TransactionVO)o2);
		}else if (o1 instanceof BuildingVO && o2 instanceof BuildingVO) {
			return this.compareBuildingVO((BuildingVO)o1, (BuildingVO)o2);
		}else if (o1 instanceof SectSta && o2 instanceof SectSta) {
			return this.compareSectSta((SectSta)o1, (SectSta)o2);
		}else if (o1 instanceof CustomerHouseVO && o2 instanceof CustomerHouseVO) {
			return this.compareCustomerHouseVO((CustomerHouseVO)o1, (CustomerHouseVO)o2);
		}else if (o1 instanceof ThingHandoverItemVO && o2 instanceof ThingHandoverItemVO) {
			return this.compareThingHandoverItemVO((ThingHandoverItemVO)o1, (ThingHandoverItemVO)o2);
		}else if (o1 instanceof SendDocumentItemConfigVO && o2 instanceof SendDocumentItemConfigVO) {
			return this.compareSendDocumentItemConfigVO((SendDocumentItemConfigVO)o1, (SendDocumentItemConfigVO)o2);
		}else if (o1 instanceof PerfectItemTypeConfigVO && o2 instanceof PerfectItemTypeConfigVO) {
			return this.comparePerfectItemTypeConfigVO((PerfectItemTypeConfigVO)o1, (PerfectItemTypeConfigVO)o2);
		}else if (o1 instanceof ContractorInfoConfigVO && o2 instanceof ContractorInfoConfigVO) {
			return this.compareContractorInfoConfigVO((ContractorInfoConfigVO)o1, (ContractorInfoConfigVO)o2);
		}else if (o1 instanceof ComLog4ceBizLogInfoVO && o2 instanceof ComLog4ceBizLogInfoVO) {
			return this.compareComLog4ceBizLogInfoVO((ComLog4ceBizLogInfoVO)o1, (ComLog4ceBizLogInfoVO)o2);
		}

		return 0;
	}

	/**
	 * 功能描述: 比较两个ChooseHouseVO的先后顺序，
	 * 排序它们的楼栋编码属性及selectText属性 <br>
	 * @param chooseHouseVO1
	 * @param chooseHouseVO2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareChooseHouseVO(ChooseHouseVO chooseHouseVO1, ChooseHouseVO chooseHouseVO2){
	    Integer seqNo1 = chooseHouseVO1.getBuildSeqNo();
        Integer seqNo2 = chooseHouseVO2.getBuildSeqNo();
        if (seqNo1 != null && seqNo2 != null) {
        	if (seqNo1.intValue() != seqNo2.intValue()) {
                return seqNo1 - seqNo2;
            }
		}

		return this.getTortuouslyComparator().tortuouslyCompareString(chooseHouseVO1.getSelectText(), chooseHouseVO2.getSelectText());
	}

	/**
	 * 功能描述: 比较两个ChooseHouseVO的先后顺序，
	 * 排序它们的楼栋编码属性及selectText属性 <br>
	 * @param chooseHouseVO1
	 * @param chooseHouseVO2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareComLog4ceBizLogInfoVO(ComLog4ceBizLogInfoVO chooseHouseVO1, ComLog4ceBizLogInfoVO chooseHouseVO2){
	    String seqNo1 = chooseHouseVO1.getOrderKey();
        String seqNo2 = chooseHouseVO2.getOrderKey();

		return this.getTortuouslyComparator().tortuouslyCompareString(seqNo1, seqNo2);
	}

	/**
	 * 功能描述: 比较两个java日期 <br>
	 * @param d1
	 * @param d2
	 * @param isDesc 是否倒序
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-9-16  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareDate(Date d1, Date d2,boolean isDesc){
		if (d1.before(d2)) {
			return isDesc?1:-1;
		}else if (d1.after(d2)) {
			return isDesc?-1:1;
		}
		return 0;
	}

	/**
	 * 功能描述: 比较两个单元的先后顺序，排序它们的名称属性 <br>
	 * @param houseGrp1
	 * @param houseGrp2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareHouseGrp(HouseGrp houseGrp1, HouseGrp houseGrp2){
		return this.compareString(houseGrp1.getName(), houseGrp2.getName());
	}

	/**
	 * </p>功能描述: 比较两个字符串的大小顺序。</p>
	 * <ol>
	 * <li>如果这两个字符串可以被解析为数字，
	 * 则比较它们的字面等值数(使用<code>java.math.BigInteger</code>解析)。
	 * 对于汉字，使用的是国标一级字库顺序排序(拼音排序)。</li>
	 * </ol>
	 * @param s1
	 * @param s2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareString(String s1, String s2){
		try {
			BigInteger bi1 = new BigInteger(s1);
			BigInteger bi2 = new BigInteger(s2);
			return bi1.compareTo(bi2);
		} catch (NumberFormatException ne) {
            this.logger.debug(ne.getLocalizedMessage());
		}
		s1 = this.getPYString(s1);
		s2 = this.getPYString(s2);

		int len1 = s1.length();
		int len2 = s2.length();
		int n = Math.min(len1, len2);
		char v1[] = s1.toCharArray();
		char v2[] = s2.toCharArray();
		int pos = 0;

		while (n-- != 0) {
			char c1 = v1[pos];
			char c2 = v2[pos];

			if (c1 != c2) {
				return c1 - c2;
			}
			pos++;
		}
		return len1 - len2;
	}

	/**
	 * 功能描述: 比较两个ChooseHouseVO的先后顺序，排序它们的selectText属性 <br>
	 * @param chooseHouseVO1
	 * @param chooseHouseVO2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareTransactionVO(TransactionVO transactionVO1, TransactionVO transactionVO2){
	    Date handTime1 = transactionVO1.getHandTime();
	    Date handTime2 = transactionVO2.getHandTime();

	    if (BlankUtil.isBlank(handTime1)
	    		&& !BlankUtil.isBlank(handTime2)) {
			return -1;
		}else if (BlankUtil.isBlank(handTime1)
	    			&& BlankUtil.isBlank(handTime2)) {
			return 0;
		}else if (!BlankUtil.isBlank(handTime1)
	    			&& BlankUtil.isBlank(handTime2)) {
			return 1;
		}

		return this.compareDate(handTime1, handTime2, true);
	}

	/**
	 * 功能描述: 比较两个ChooseHouseVO的先后顺序，排序它们的selectText属性 <br>
	 * @param chooseHouseVO1
	 * @param chooseHouseVO2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareBuildingVO(BuildingVO buildingVO1, BuildingVO buildingVO2){
	    Integer seqNo1 = buildingVO1.getSeqNo();
	    Integer seqNo2 = buildingVO2.getSeqNo();
	    if (BlankUtil.isBlank(seqNo1)
	    		&& !BlankUtil.isBlank(seqNo2)) {
			return -1;
		}else if (BlankUtil.isBlank(seqNo1)
	    			&& BlankUtil.isBlank(seqNo2)) {
			return 0;
		}else if (!BlankUtil.isBlank(seqNo1)
	    			&& BlankUtil.isBlank(seqNo2)) {
			return 1;
		}

		return seqNo1 - seqNo2;
	}

	/**
	 * 功能描述: 比较两个CustomerHouseVO的先后顺序，排序它们的houseNumber属性 <br>
	 * @param cHouseVo1
	 * @param cHouseVo2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareCustomerHouseVO(CustomerHouseVO cHouseVo1, CustomerHouseVO cHouseVo2){
	    String hno1 = cHouseVo1.getHouseNumber();
	    String hno2 = cHouseVo2.getHouseNumber();
	    return this.compareString(hno1, hno2);
	}

	private int compareThingHandoverItemVO(ThingHandoverItemVO itemvo1, ThingHandoverItemVO itemvo2){
	    String hno1 = itemvo1.getHouseNumber();
	    String hno2 = itemvo2.getHouseNumber();
	    int result= this.compareString(hno1, hno2);
	    if(result == 0){
	    	 String hn1 = itemvo1.getThingHandoverCongfigName();
	 	     String hn2 = itemvo2.getThingHandoverCongfigName();
	 	     result =  this.compareString(hn1, hn2);
	    }
	    return result;
	}

	private int compareSendDocumentItemConfigVO(SendDocumentItemConfigVO config1, SendDocumentItemConfigVO config2){
	    if(BlankUtil.isBlank(config1.getSequence()) || BlankUtil.isBlank(config2.getSequence())){
	    	 return this.compare(config1.getSendDocumentItemName(), config1.getSendDocumentItemName());
	    }else{
			short o1 = config1.getSequence();
		    short o2 = config1.getSequence();
		    return this.compare(o1, o2);
	    }
	}

	private int comparePerfectItemTypeConfigVO(PerfectItemTypeConfigVO config1, PerfectItemTypeConfigVO config2){
		  if(BlankUtil.isBlank(config1.getSequence()) || BlankUtil.isBlank(config2.getSequence())){
		    	 return this.compare(config1.getPerfectItemTypeName(), config1.getPerfectItemTypeName());
		    }else{
			short o1 = config1.getSequence();
		    short o2 = config1.getSequence();
		    return this.compare(o1, o2);
		   }
	}

	private int compareContractorInfoConfigVO(ContractorInfoConfigVO config1, ContractorInfoConfigVO config2){
		if(BlankUtil.isBlank(config1.getSequence()) || BlankUtil.isBlank(config2.getSequence())){
	    	 return this.compare(config1.getContractorInfoName(), config1.getContractorInfoName());
	    }else{
		short o1 = config1.getSequence();
	    short o2 = config1.getSequence();
	    return this.compare(o1, o2);
	    }
	}



	/**
	 * 功能描述: 比较两个ChooseHouseVO的先后顺序，排序它们的selectText属性 <br>
	 * @param chooseHouseVO1
	 * @param chooseHouseVO2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int compareSectSta(SectSta s1, SectSta s2){
	    BigDecimal seqNo1 = s1.getStartPoint();
	    BigDecimal seqNo2 = s2.getStartPoint();

	    return seqNo1.compareTo(seqNo2);
	}

	/**
     * 取单个字符的拼音声母
     * @param c  要转换的单个汉字
     * @return String 拼音声母
     */
    private String getPYChar(String c) {
        byte[] array = c.getBytes();
        int i = (short) (array[0] - '\0' + 256) * 256
                + ((short) (array[1] - '\0' + 256));
        if (i < 0xB0A1) {
            return "*";
        } else if (i < 0xB0C5) {
            return "a";
        } else if (i < 0xb2c1) {
            return "b";
        } else if (i < 0xB4EE) {
            return "c";
        } else if (i < 0xB6EA) {
            return "d";
        } else if (i < 0xB7A2) {
            return "e";
        } else if (i < 0xB8C1) {
            return "f";
        } else if (i < 0xB9FE) {
            return "g";
        } else if (i < 0xBBF7) {
            return "h";
        } else if (i < 0xBFA6) {
            return "j";
        } else if (i < 0xC0AC) {
            return "k";
        } else if (i < 0xC2E8) {
            return "l";
        } else if (i < 0xC4C3) {
            return "m";
        } else if (i < 0xC5B6) {
            return "n";
        } else if (i < 0xC5BE) {
            return "o";
        } else if (i < 0xC6DA) {
            return "p";
        } else if (i < 0xC8BB) {
            return "q";
        } else if (i < 0xC8F6) {
            return "r";
        } else if (i < 0xCBFA) {
            return "s";
        } else if (i < 0xCDDA) {
            return "t";
        } else if (i < 0xCEF4) {
            return "w";
        } else if (i < 0xD1B9) {
            return "x";
        } else if (i < 0xD4D1) {
            return "y";
        } else if (i < 0xD7FA) {
            return "z";
        } else
            return "*";
    }

	/**
     * 汉字转拼音缩写
     * @param str  //要转换的汉字字符串
     * @return String  //拼音缩写
     */
    private String getPYString(String str) {
    	try {
    		StringBuffer tempStr = new StringBuffer();
            int len = str.length();
            for(int i=0; i<len; i++) {
                    char c = str.charAt(i);
                    if((int)c >= 32 && (int)c <=126) {//字母和符号原样保留
                    	tempStr.append(c);// += String.valueOf(c);
                    }
                    else {//累加拼音声母
                        tempStr.append(getPYChar(String.valueOf(c)));
                    }
            }
            return tempStr.toString();
		} catch (Exception e) {
			return "";
		}
    }

    /**
	 * 功能描述: 得到一个比较实例KnottPmsComparetor <br>
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private KnottPmsComparetor getTortuouslyComparator(){
		return new KnottPmsComparetor();
	}

/**
 *
 * 	名称: com.ce.pms.common.util.KnottPmsComparetor <br>
 *  一个包含较复杂比较运算的比较器
 *
 * @author  付湘辉  <br>
 * Created on： 2008-8-8 <br>
 * @author <br>
 * update on： <br>
 * why: <br>
 */
class KnottPmsComparetor extends PmsUtilityComparator{

	private KnottPmsComparetor(){

	}

	/**
	 * </p>功能描述: 重写比较器，通常包括比较复杂的比较。</p>
	 * </p><b>1</b>：字符串的比较</p>
	 * <ol>
	 * <ul>
	 * <li>如果这两个字符串中包含有可以被解析为数字的字符匹配，
	 * 则逐个比较它们的字面等值数。对于以0开头的匹配字符，用BigInteger的构造解析值比较
	 * <ul>
	 * <li>例如："01" 构造成BigInteger后的值为 1，多个"0"被当作一个"0"看待</li>
	 * </ul>
	 * </li>
	 * </ul>
	 * <ol>
	 * @param s1
	 * @param s2
	 *
	 * @see com.ce.pms.common.util.PmsUtilityComparator#compare(java.lang.Object, java.lang.Object)
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	@Override
	public int compare(Object o1, Object o2) {
		if (o1 instanceof String && o2 instanceof String) {
			return this.tortuouslyCompareString((String)o1, (String)o2);
		}

		return super.compare(o1, o2);
	}

	/**
	 * </p>功能描述: 比较两个字符串的大小顺序，优先比较其中匹配的数值</p>
	 * <ol>
	 * <li>如果这两个字符串中包含有可以被解析为数字的字符匹配，
	 * 则逐个比较它们的字面等值数。对于以0开头的匹配字符，用BigInteger的构造解析值比较
	 * <ul>
	 * <li>例如："01" 构造成BigInteger后的值为 1，多个"0"被当作一个"0"看待</li>
	 * </ul>
	 * </li>
	 * </ol>
	 * @param s1
	 * @param s2
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-8-8  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private int tortuouslyCompareString(String s1, String s2){
		try {
			Pattern p = Pattern.compile("\\d+");

			Matcher m1 =  p.matcher(s1);
			Matcher m2 =  p.matcher(s2);
			while (m1.find() && m2.find()) {
				BigInteger bi1 = new BigInteger(m1.group());
				BigInteger bi2 = new BigInteger(m2.group());
				int res = bi1.compareTo(bi2);
				if (res!=0) {
					return res;
				}
			}
		} catch (NumberFormatException ne) {
            this.logger.debug(ne.getLocalizedMessage());
		}

		return PmsUtilityComparator.getComparator().compareString(s1, s2);
	}
}
}
